home *** CD-ROM | disk | FTP | other *** search
/ Power Programmierung 2 / Power-Programmierung CD 2 (Tewi)(1994).iso / c / library / dos / communic / pcmail / main / nmail.c < prev    next >
Encoding:
C/C++ Source or Header  |  1994-06-05  |  6.7 KB  |  240 lines

  1. /*++
  2. /* NAME
  3. /*      nmail
  4. /* SUMMARY
  5. /*      extract originator and subject from new mail received by cico
  6. /* PROJECT
  7. /*      pc-mail
  8. /* PACKAGE
  9. /*      nmail
  10. /* SYNOPSIS
  11. /*      nmail [-d debuglevel]
  12. /* DESCRIPTION
  13. /*      nmail searches for new mail files received by cico and extracts
  14. /*    the originator's name, and message subject for later use by the 
  15. /*    mail visual shell.
  16. /*
  17. /*     Return address formats we understand (in order of preference):
  18. /* .nf
  19. /*
  20. /*    From: address (full_name)    (take full_name)
  21. /*    From: full_name <address>    (take full_name)
  22. /*    From: address            (take address)
  23. /*    >From address            (take address)
  24. /*    From address            (take address)
  25. /*
  26. /* .fi
  27. /*      To avoid tampering, new files will have read-only permission.
  28. /*
  29. /*      In order to avoid corruption, control-c interrupts are disabled
  30. /*    while this program executes.
  31. /* FILES
  32. /*      In the spool directory:
  33. /*    n<seqno>    received mail message
  34. /*    h<seqno>    extracted originator name, subject
  35. /* SEE ALSO
  36. /*      path(5)         spool directory, file names
  37. /*      cico(1)         network process
  38. /*      mail(1)       visual mail shell
  39. /* DIAGNOSTICS
  40. /*      Exit status zero when no errors were detected, nonzero in case of file
  41. /*      access errors. See status(5) for error codes.
  42. /* AUTHOR(S)
  43. /*      W.Z. Venema
  44. /*      Eindhoven University of Technology
  45. /*      Department of Mathematics and Computer Science
  46. /*      Den Dolech 2, P.O. Box 513, 5600 MB Eindhoven, The Netherlands
  47. /* CREATION DATE
  48. /*      Tue Mar 31 20:14:11 GMT+1:00 1987
  49. /* LAST MODIFICATION
  50. /*    90/01/22 13:02:20
  51. /* VERSION/RELEASE
  52. /*    2.1
  53. /*--*/
  54.  
  55. #include <stdio.h>
  56. #include <signal.h>
  57. #include <time.h>
  58. #include <ctype.h>
  59. #include <varargs.h>
  60.  
  61. #include "defs.h"
  62. #include "ndir.h"
  63. #include "path.h"
  64. #include "status.h"
  65. #include "ms_parse.h"
  66.  
  67. extern struct tm *localtime();        /* system functions */
  68.  
  69. hidden void parse_args();        /* forward declarations */
  70. hidden void newmail();
  71. hidden void extract();
  72. hidden void usage();
  73.  
  74. hidden int dflag = 0;            /* debugging option */
  75.  
  76. #define debug    if (dflag) printf
  77.  
  78. public char *progname = "nmail";
  79.  
  80. main(argc, argv)
  81. int     argc;
  82. char  **argv;
  83. {
  84.     signal(SIGINT, SIG_IGN);            /* disable ctrl-c */
  85.     parse_args(argc, argv);            /* parse command args */
  86.     if (pathinit())                /* get path info */
  87.     exit(E_NOSPOOL);            /* bad MAILDIR variable */
  88.     umask(0222);                /* make files read-only */
  89.     newmail();                    /* get headers from new mail */
  90.     exit(0);
  91.     /* NOTREACHED */
  92. }
  93.  
  94. /* parse_args - process command-line arguments */
  95.  
  96. hidden void parse_args(argc, argv)
  97. int     argc;
  98. char  **argv;
  99. {
  100.     while (--argc && *++argv && **argv == '-') {/* process options */
  101.     switch (*++*argv) {
  102.     case 'd':                /* turn debugging on */
  103.         if (--argc == 0)
  104.         usage("missing debugging level argument");
  105.         if ((dflag = atoi(*++argv)) < 0 || dflag > 9)
  106.         dflag = 0;
  107.         break;
  108.     default:                /* unknown option */
  109.         usage("invalid option: -%c", **argv);
  110.         break;
  111.     }
  112.     }
  113.  
  114.     /* check for extraneous arguments */
  115.  
  116.     if (argc > 0)
  117.     usage("unexpected argument: %s", *argv);
  118. }
  119.  
  120. /* scan for new mail that hasn't gotten yet a metafile */
  121.  
  122. hidden void newmail()
  123. {
  124.     register DIR *dp;
  125.     struct direct *de;
  126.     unsigned msgno;
  127.  
  128.     debug("directory: \"%s\"\n", maildir);
  129.  
  130.     /*
  131.      * Scan the spool directory for newly-arrived mail.
  132.      * 
  133.      * Incoming mail message files have a name of "n<seqno>". The originator
  134.      * name is normally present in files with names "h<seqno>" or "o<seqno>".
  135.      * The presence of an "o" file implies that the file "n<seqno>" has been
  136.      * read by the user. An "h" file means that the user has not yet read the
  137.      * message file.
  138.      * 
  139.      * If a message file has no corresponding "h" or "o" file we assume it is a
  140.      * new mail message and create an "h" file with the name of the
  141.      * originator and the subject of the message.
  142.      */
  143.  
  144.     if ((dp = opendir(maildir)) == 0)
  145.     exit(E_NOSPOOL);
  146.  
  147.     while (de = readdir(dp)) {
  148.     debug("nmail: file \"%s\"\n", de->d_name);
  149.     if (de->d_name[0] == NEW_MESG
  150.         && (msgno = seqno(de->d_name))) {
  151.         if (access(old_meta(msgno), 4) == 0) {
  152.          /* already marked as read */ ;
  153.         } else if (access(new_meta(msgno), 4) == 0) {
  154.          /* already marked as unread */ ;
  155.         } else {                /* create meta file */
  156.         extract(new_mesg(msgno), new_meta(msgno));
  157.         }
  158.     }
  159.     }
  160.     closedir(dp);
  161. }
  162.  
  163. /* extract - extract originator and subject info from mail file to meta file */
  164.  
  165. hidden void extract(mail, meta)
  166. char   *mail;
  167. char   *meta;
  168. {
  169.     FILE   *mesgfp,
  170.            *metafp;
  171.     char    line[MAXLINE];
  172.     char    from[MAXLINE];            /* name of sender */
  173.     char    subj[MAXLINE];            /* message subject */
  174.     int     context = MS_UUCP;
  175.  
  176.     debug("-- \"%s\" -> \"%s\"\n", mail, meta);
  177.  
  178.     if ((mesgfp = fopen(mail, "r")) == NULL)    /* cannot open existing file */
  179.     exit(E_SYSFAIL);
  180.  
  181.     strcpy(from, "Somewhere");            /* default originator */
  182.     subj[0] = '\0';                /* initialize subject */
  183.  
  184.     /*
  185.      * Some mailers generate real headers, separated from the message body by
  186.      * an empty line. So we stop when we find an empty line. Other mailers
  187.      * have no headers, so we stop when we see no header line. The following
  188.      * algorithm tries to extract the real user name if possible, otherwise
  189.      * it takes whatever it can get.
  190.      */
  191.  
  192.     while ((context != MS_BODY) && fgets(line, sizeof(line), mesgfp)) {
  193.     switch (context = ms_parse(context, line)) {
  194.     case MS_UUCP:
  195.         if (sscanf(line, "%*[>] From %s", from) != 1)
  196.         (void) sscanf(line, "From %s", from);
  197.         break;
  198.     case MS_HEADER:
  199.         if (hscanf(line, "Subject:", " %[^\n]", subj) == 0
  200.         && hscanf(line, "From:", " %*s ( %[^)] )", from) == 0)
  201.         (void) hscanf(line, "From:", " %[^<] <", from);
  202.         break;
  203.     }
  204.     }
  205.  
  206.     /* carefully check all went well */
  207.  
  208.     if (ferror(mesgfp))                /* sorry, read problem */
  209.     exit(E_READERR);
  210.     if ((metafp = fopen(meta, "w")) == NULL)    /* cannot create metafile */
  211.     exit(E_WRITERR);
  212.     fprintf(metafp, "%s\n%s\n", from, subj);    /* write originator, subject */
  213.     if (ferror(metafp)) {
  214.     (void) fclose(metafp);            /* ms-dog needs this! */
  215.     (void) chmod(meta, 0666);        /* sorry, write problem */
  216.     (void) unlink(meta);            /* delete metafile */
  217.     exit(E_WRITERR);
  218.     }
  219.     (void) fclose(mesgfp);
  220.     (void) fclose(metafp);
  221. }
  222.  
  223. /* usage - explain what is wrong */
  224.  
  225. /* VARARGS */
  226.  
  227. hidden void usage(va_alist) 
  228. va_dcl
  229. {
  230.     va_list ap;
  231.     char   *fmt;
  232.  
  233.     va_start(ap);
  234.     fmt = va_arg(ap, char *);
  235.     vfprintf(stderr, fmt, ap);
  236.     va_end(ap);
  237.     fprintf(stderr, "\nusage: nmail [-d debugging_level]\n");
  238.     exit(2);
  239. }
  240.